﻿namespace WebPacker.Helpers
{
	using System;
	using System.IO;
	using System.Threading;

	internal static class VirtualPathHelper
	{
		private static readonly char UrlSeparator = '/';
		private static readonly char DirectorySeparator = Path.DirectorySeparatorChar;
		private static readonly StringComparison comparison = StringComparison.CurrentCultureIgnoreCase;

		static VirtualPathHelper()
		{
			var domain = Thread.GetDomain();

			var appPath = domain.GetData(".appPath") as string;
			var virtualPath = domain.GetData(".appVPath") as string;

			if (virtualPath != null && virtualPath.Length > 0 && virtualPath[0] != '/')
			{
				virtualPath = '/' + virtualPath;
			}

			ApplicationPhysicalPath = appPath ?? string.Empty;
			ApplicationVirtualPath = virtualPath ?? string.Empty;
		}

		internal static string ApplicationVirtualPath { get; set; }

		internal static string ApplicationPhysicalPath { get; set; }

		public static string ToVirtualPath(string path)
		{
			if (path[0] == '~')
			{
				path = CombineUri(ApplicationVirtualPath, path.Substring(1));
			}
			else
			{
				var length = ApplicationPhysicalPath.Length;

				if (path.Length > length + 1 && path.StartsWith(ApplicationPhysicalPath, comparison))
				{
					var relativePath = path.Substring(length);

					if (DirectorySeparator != UrlSeparator)
					{
						relativePath = relativePath.Replace(DirectorySeparator, UrlSeparator);
					}

					path = CombineUri(ApplicationVirtualPath, relativePath);
				}
			}

			return path;
		}

		public static string NormalizePath(string path)
		{
			return path.Replace(UrlSeparator, DirectorySeparator);
		}

		public static bool Equals(string path1, string path2)
		{
			return 0 == string.Compare(path1, path2, comparison);
		}

		public static string ToPhisicalPath(string path)
		{
			if (string.IsNullOrEmpty(path))
			{
				throw new ArgumentNullException("path");
			}

			if (Path.DirectorySeparatorChar != UrlSeparator)
			{
				path = path.Replace(UrlSeparator, Path.DirectorySeparatorChar);
			}

			if (path[0] == '~')
			{
				path = CombinePath(ApplicationPhysicalPath, path.Substring(1));
			}

			return path;
		}

		public static string CombineUri(string path1, string path2)
		{
			return Combine(path1, path2, UrlSeparator);
		}

		public static string CombinePath(string path1, string path2)
		{
			return Combine(path1, path2, DirectorySeparator);
		}

		private static string Combine(string path1, string path2, char separator)
		{
			if (string.IsNullOrEmpty(path1))
			{
				return path2 ?? string.Empty;
			}
			else if (string.IsNullOrEmpty(path2))
			{
				return path1 ?? string.Empty;
			}
			else if (path1[path1.Length - 1] == separator)
			{
				if (path2[0] == separator)
				{
					return path1 + path2.Substring(1);
				}

				return path1 + path2;
			}
			else
			{
				if (path2[0] == separator)
				{
					return path1 + path2;
				}

				return path1 + separator + path2;
			}
		}
	}
}
